package com.klangner.go.app.strategy;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import com.klangner.game.ai.ab.IMoveSelector;
import com.klangner.game.board.BoardPosition;
import com.klangner.game.board.IBoard;
import com.klangner.game.board.Move;
import com.klangner.go.app.rules.BoardModel;
import com.klangner.go.app.rules.GobanLocation;
import com.klangner.go.app.rules.StonesGroupOld;


/**
 * This class find possibles moves
 * @author Krzysztof Langner
 * @version 1.0
 */
public class AliceMoveSelector implements IMoveSelector{

  //----------------------------------------------------------------------------
  /**
   * Constructor
   */
  public AliceMoveSelector() {
  }


  //----------------------------------------------------------------------------
  /**
   * @see IMoveSelector#getCandidates(IBoard, int)
   */
    public List<Move> getCandidates( BoardModel board, int color ) {

      Vector<Move> candidateMoves = new Vector<Move>();

      // Select as possible next moves just the contact moves
      // Not as a best strategy :-) but as a reasonable filtering method
      Iterator<Move> contactMoves = getContactMoves(board);

      if (!contactMoves.hasNext()) {
      	contactMoves = board.legalMoves();
      }

      for ( ; contactMoves.hasNext(); ) {
      	BoardPosition gl = contactMoves.next();
        Move move = new Move(gl.getX(), gl.getY(), board.getTurnColor());

        candidateMoves.addElement( move );
      }

      return candidateMoves;
    }


  //----------------------------------------------------------------------------
  // returns an iterator with the possible contact moves
  private Iterator<Move> getContactMoves(BoardModel board) {

    Enumeration<StonesGroupOld> 	blackGroups, whiteGroups;
    Set<GobanLocation> 				result;
    Vector<Move>							moves = new Vector<Move>();

    result = new HashSet<GobanLocation>();

    whiteGroups = board.getWhiteGroups().elements();
    blackGroups = board.getBlackGroups().elements();

    // add black groups' liberties to the list
    for (;blackGroups.hasMoreElements();) {
      // get current group's liberties
      result.addAll((blackGroups.nextElement()).getLiberties());
    }

    // add white groups' liberties to the list
    for (;whiteGroups.hasMoreElements();) {
      // get current group's liberties
      result.addAll((whiteGroups.nextElement()).getLiberties());
    }

    Iterator<GobanLocation>	it = result.iterator();
    while( it.hasNext() ){
    	GobanLocation gl = it.next();
    	moves.add(new Move(gl.x, gl.y, board.getTurnColor()));
    }
    
    return filterLegalMoves( board, moves.iterator() ).iterator();

  }


  //----------------------------------------------------------------------------
  /**
   * It filters the <list> of Moves (second argument), returning only those
   * Moves which are legal in the given <goPosition>
   */
  private Vector<Move> filterLegalMoves(BoardModel board, Iterator<Move> list) {

    Vector<Move> moves = new Vector<Move>();

    int nextColor = board.getTurnColor();

    while (list.hasNext() ) {
    	Move location = list.next();
        Move currentMove = new Move(location.getX(), location.getY(), nextColor);

            // only add the legal moves in the list
        if (board.isLegalMove(currentMove))
            moves.add(currentMove);
    }

    return moves;
  }


}